﻿using System.Collections.Generic;
using DL.Tools;
using JetBrains.Annotations;
using UnityEngine;

namespace DL.UIBinding
{
    public abstract class InfinityContext
    {
        protected int m_Index;
        protected Vector2 m_LocalPos;

        protected InfinityItem m_Item;

        // protected bool m_Init;
        public int Index
        {
            get => m_Index;
        }

        public Vector2 LocalPos
        {
            get => m_LocalPos;
        }

        public InfinityItem Item
        {
            get => m_Item;
            set => m_Item = value;
        }

        /// <summary>
        /// 开放刷新接口
        /// </summary>
        public virtual void Refresh()
        {
            if(m_Item != null) m_Item.Refresh();
        }

        //重新计算下标和位置
        public void RefreshChange(int index,Vector2 localPos)
        {
            m_Index = index;
            m_LocalPos.Set(localPos.x, localPos.y);
            // Debugger.EO_Log(m_Index + "更新计算本地坐标" + m_LocalPos);
        }

        private bool m_Dirty;
        public bool Dirty => m_Dirty;
        /// <summary>
        /// 设置脏位
        /// </summary>
        public void SetDirty(bool dirty)
        {
            m_Dirty = dirty;
        }
    }

    /// <summary>
    /// 专用于循环列表的收集器
    /// </summary>
    public class InfinityCollection<T> : IInfinityCollection<T> where T : InfinityContext
    {
        private readonly List<T> m_Items = new List<T>();
        private InfiniteScrollView m_InfiniteScrollView;

        public InfinityCollection([NotNull] InfiniteScrollView infiniteScrollView)
        {
            m_InfiniteScrollView = infiniteScrollView;
            m_InfiniteScrollView.Init(this);
        }

        public int Count => m_Items.Count;
        
        //数据操作方法  Add 和 Insert Remove 方法 
        
        public void Add(T item) => Insert(item, this.m_Items.Count);
        
        public void Insert(T item, int index)
        {
            if (index < 0 || index >= this.m_Items.Count)
                index = this.m_Items.Count;
            this.m_Items.Insert(index, item);
            
            //如果插在中间，那么它和它之后的都需要重新计算
            Refresh(index);
        }
        
        //移除
        public void Remove(int index)
        {
            if (m_Items.Count <= index) return;
            var item = m_Items[index];
            m_Items.Remove(item);
            //回收这个Item
            m_InfiniteScrollView.RecycleItem(item.Item);
            Refresh(index);
        }
        
        public void Remove(T item)
        {
            for (int index = 0; index < this.m_Items.Count; ++index)
            {
                if ((object)this.m_Items[index] == (object)item)
                {
                    this.Remove(index);
                    break;
                }
            }
        }

        //刷新后面的数据，包括自己
        private void Refresh(int index = 0)
        {
            for (int i = index; i < m_Items.Count; i++)
            {
                var item = GetItem(i);
                //后面的数据信息都是错的
                item.SetDirty(true);
            }
            
            //准备通知视图去更新显示  
            m_InfiniteScrollView.ReUpdateData(index);
            // Debug.Log("收集器数量改变，通知视图更新");
        }

        public T GetItem(int index) => index < 0 || index >= this.m_Items.Count ? default(T) : this.m_Items[index];

        public void JumpToIndex(int index, float delay) => m_InfiniteScrollView.JumpToIndex(index, delay);

    }

    //方便使用协变
    public interface IInfinityCollection<out T> where T : InfinityContext
    {
        public T GetItem(int index);
        int Count { get;}
    }
}